package com.zz.framework.core.xdialog.base

import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import androidx.activity.enableEdgeToEdge
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentManager
import androidx.viewbinding.ViewBinding

/**
 * DialogFragment的基类
 * 1.系统默认onCreateDialog方法返回一个Dialog对象,对其不做处理
 * 2.主要操作onCreateView方法
 * 因为DialogFragment继承自Fragment,所以可以在onCreteView()方法返回xml布局,
 * 该布局在onActivityCreated()方法中,设置给系统之前创建的Dialog对象
 * 3.对应使用Dialog不同部分包括
 * a.viewbinding布局
 * b.宽高
 * c.位置
 * d.背景色
 * e.透明度
 * f.是否可以点击空白处隐藏
 * 控制方法在onStart处理,
 * 4.暴露方法:界面中控件处理和点击事件处理
 * 5.监听回调,很多弹窗需要输入信息,然后将输入的信息通过回调的方法返回
 * 6.当设备Configure属性变化时,数据保存和恢复处理
 *
 * Copyright © 2025 zhun All rights reserved.
 * @author: Zha0Zhun 1820022519@qq.com
 * @version: V1.0
 */
abstract class BaseDialogFragment : DialogFragment() {
    protected abstract fun getViewBindingClass(): Class<out ViewBinding>?
    private var _binding: ViewBinding? = null
    protected val binding get() = _binding

    protected abstract fun bindView(binding: ViewBinding)

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        _binding = createViewBinding(getViewBindingClass(), inflater, container)
        _binding?.let {
            bindView(it)
        }
        return binding?.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return Dialog(requireContext()).apply {
            requestWindowFeature(Window.FEATURE_NO_TITLE) // 防止 requestFeature() 异常
        }
    }

    private fun <VB : ViewBinding> createViewBinding(bindingClass: Class<VB>?, parent: ViewGroup): VB {
        val inflater = LayoutInflater.from(parent.context)
        val method = bindingClass?.getMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.java)
        return method?.invoke(null, inflater, parent, false) as VB
    }

    private fun <VB : ViewBinding> createViewBinding(bindingClass: Class<VB>?, inflater: LayoutInflater, parent: ViewGroup?): VB? {
        val method = bindingClass?.getMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.java)
        return method?.invoke(null, inflater, parent, false) as? VB
    }


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        dialog?.apply {
            setCanceledOnTouchOutside(isCancelableOutside())
            window?.let {
                if (getDialogAnimationRes() > 0) {
                    it.setWindowAnimations(getDialogAnimationRes())
                }
            }
            getOnKeyListener()?.let { setOnKeyListener(it) }
        }
    }

    protected open fun getOnKeyListener(): DialogInterface.OnKeyListener? = null

    override fun onStart() {
        super.onStart()
        dialog?.window?.apply {
            setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
            attributes = attributes.apply {
                width = if (getDialogWidth() > 0) getDialogWidth() else WindowManager.LayoutParams.WRAP_CONTENT
                height = if (getDialogHeight() > 0) getDialogHeight() else WindowManager.LayoutParams.WRAP_CONTENT
                dimAmount = getDimAmount()
                gravity = getGravity()
            }
        }
    }

    open fun getGravity(): Int = Gravity.CENTER
    open fun getDialogHeight(): Int = WindowManager.LayoutParams.WRAP_CONTENT
    open fun getDialogWidth(): Int = WindowManager.LayoutParams.WRAP_CONTENT
    open fun getDimAmount(): Float = DEFAULT_DIM_AMOUNT
    open fun getFragmentTag(): String = TAG
    open fun isCancelableOutside(): Boolean = true
    protected open fun getDialogAnimationRes(): Int = 0

    fun show(fragmentManager: FragmentManager) {
        show(fragmentManager, getFragmentTag())
    }

    companion object {
        const val TAG = "XDialog"
        private const val DEFAULT_DIM_AMOUNT = 0.2F
        fun getScreenWidth(context: Context): Int = context.resources.displayMetrics.widthPixels
        fun getScreenHeight(context: Context): Int = context.resources.displayMetrics.heightPixels
    }
}
